package effect;

import board.BoardUtil;
import board.PatternType;
import character.MyCharacter;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import game.DataStore;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import misc.Vector3i;

public abstract class Effect implements Cloneable {
    protected String effectName;
    protected MyCharacter owner;
    protected EffectType effectType;
    protected int baseSpeed;
    protected PatternType rangePattern; //Note: PatternType.LINE is NOT a valid RangePattern
    protected int rangeSize;
    protected float baseEffectAmount;
    protected int baseDuration;
    protected ParticleEmitter particleEffect;

    @Deprecated
    protected Effect() {}
    
    public Effect(MyCharacter owner) {
	this.owner = owner;
	init();
    }

    private void init() { //temporary for development
	/** Uses Texture from jme3-test-data library! */
	particleEffect = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
	Material mat_red = new Material(DataStore.assetManager, "Common/MatDefs/Misc/Particle.j3md");
	mat_red.setTexture("Texture", DataStore.assetManager.loadTexture("Effects/Explosion/flame.png"));
	particleEffect.setMaterial(mat_red);
	particleEffect.setImagesX(2);
	particleEffect.setImagesY(2); // 2x2 texture animation
	particleEffect.setEndColor(new ColorRGBA(1f, 0f, 0f, 1f));   // red
	particleEffect.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
	particleEffect.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 2, 0));
	particleEffect.setStartSize(0.6f);
	particleEffect.setEndSize(0.1f);
	particleEffect.setGravity(0f,0f,0f);
	particleEffect.setLowLife(0.5f);
	particleEffect.setHighLife(3f);
	particleEffect.getParticleInfluencer().setVelocityVariation(0.3f);
    }

    public String getEffectName() {
	return effectName;
    }
    public void setEffectName(String effectName) {
	this.effectName = effectName;
    }
    public EffectType getEffectType() {
        return effectType;
    }
    public void setEffectType(EffectType effectType) {
        this.effectType = effectType;
    }
    public MyCharacter getOwner() {
	return owner;
    }
    public void setOwner(MyCharacter owner) {
	this.owner = owner;
    }
    public PatternType getRangePattern() {
	return rangePattern;
    }
    public void setRangePattern(PatternType rangePattern) {
	this.rangePattern = rangePattern;
    }
    public int getRangeSize() {
	return rangeSize;
    }
    public void setRangeSize(int rangeSize) {
	this.rangeSize = rangeSize;
    }
    public int getBaseSpeed() {
	return baseSpeed;
    }
    public void setBaseSpeed(int baseSpeed) {
	this.baseSpeed = baseSpeed;
    }
    public Collection<Vector3i> getLocationsInRange() {
        Set<Vector3i> locationsInRange = new HashSet<Vector3i>();
	for(Vector3i occupiedLocation : owner.getOccupiedLocations())
	    locationsInRange.addAll(BoardUtil.getPatternLocations(rangePattern, rangeSize, true, occupiedLocation));
        return locationsInRange;
    }
    
    public float getBaseEffectAmount() {
        return baseEffectAmount;
    }
    public void setBaseEffectAmount(float baseEffectAmount) {
	this.baseEffectAmount = baseEffectAmount;
    }

    public int getBaseDuration() {
        return baseDuration;
    }
    public void setBaseDuration(int baseDuration) {
        this.baseDuration = baseDuration;
    }
    
    public ParticleEmitter getParticleEffect() {
        particleEffect.setLocalTranslation(getParticleEffectLocation());
        return particleEffect;
    }
    protected abstract Vector3f getParticleEffectLocation();
    public float getParticleEffectTime() {
	return 3f;
    }
    
    @Override
    public Effect clone() {
        try {
            return (Effect)super.clone();
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(Effect.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    @Override
    /** The default requirement for an Effect's equals is just to be of the same class.
     * Override this if a subclass requires other stipulations.
     */
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        return hash;
    }
}
